jQuery(function($){
	// create a singleton to manage demo operations
	var demo = $.demo = {
		// hold active menu item
		$active1: $([]), $active2: $([]),
		$hover1: $([]), $hover2: $([]),
		// the plugin menus
		$main: $('#menu dt:eq(1)').button().popdown({
			align: "left|left top|bottom",
		//	showEvent: "click",
			classes: { 
				open: "ux-button-checked",
				div: "menu-popdown-div"
				},
			html: $('#main_menu')
				.bind("mouseover mouseleave", function( ev ){
					demo.$hover1.removeClass("menu-hover");
					if ( ev.type == "mouseover" )
						demo.$hover1 = $( ev.target ).closest("li").addClass("menu-hover");
					}),
			onShow: function( ev, $div ){
				demo.$sub.ux("popdown.hide");
				$div.slideDown("fast");
				}	
			}), 
		$mainpop: $('#main_menu'),
		// additional navigation
		$prev: $('#menu dt:eq(0)').button()
			.click(function(){
				var $prev = demo.$active2.parent().prevAll('li:has(a)').find('a'), hash;
				if ( !$prev.length ) 
					$prev = demo.$active1.parent().prevAll('li:has(a)').find('a');
				if ( !$prev.length ) 
					$prev = $('#main_menu').find("a:last");
				if ( hash = $prev.attr('href') ) window.location = hash;										   
				}),
		$next: $('#menu dt:eq(3)').button()
			.click(function(){
				var $next = demo.$active2.parent().nextAll('li:has(a)').find('a'), hash;
				if ( !$next.length ) 
					$next = demo.$active1.parent().nextAll('li:has(a)').find('a');
				if ( !$next.length ) 
					$next = $('#main_menu').find("a:first");
				if ( hash = $next.attr('href') ) window.location = hash;
				}),
		// the demo file sub menu
		$sub: $('#menu dt:eq(2)').button().popdown({
			align: "left|left top|bottom",
		//	showEvent: "click",
			classes: { 
				open: "ux-button-checked",
				div: "menu-popdown-div"
				},
			html: $('#sub_menu')
				.bind("mouseover mouseleave", function( ev ){
					demo.$hover2.removeClass("menu-hover");
					if ( ev.type == "mouseover" )
						demo.$hover2 = $( ev.target ).closest("li").addClass("menu-hover");
					}),
			onShow: function( ev, $div ){
				demo.$main.ux("popdown.hide");
				$div.slideDown("fast");
				}
			}).hide(),
		$subpop: $('#sub_menu'),
		// the page container
		$wrap: $('#everything'),
		// the demo container
		$demo: $('#demo_div'),
		// the demo source edit textarea
		$code: $('#editor_div'),
		// the codemirror instance
		editor: new CodeMirror(	$('#editor_div')[0], {
		    content: '<p>Select a plugin to start playing with demos. You may view and edit the source code of each demo using the buttons above.</p>',
			width: "100%",
			height: "100%",
			indentUnit: 3,
		    tabMode: "shift",
			textWrapping: false,
			//lineNumbers: true,
			path: "codemirror/js/",
			parserfile: [
				"parsexml.js", 
				"parsecss.js", 
				"tokenizejavascript.js", 
				"parsejavascript.js", 
				"parsehtmlmixed.js"
				],
			stylesheet: [
				"codemirror/css/xmlcolors.css", 
				"codemirror/css/jscolors.css", 
				"codemirror/css/csscolors.css"
				],
			initCallback: function(){
				demo.codeMirrorReady = true;
				demo.execute();
				}
			}),
		// the <div> that holds the source code and buttons
		$source: $('#source'),
		// toggle buttons
		$code_btn: $('#tab_code')
			.button({
				type: "radio",
				name: "tabcodemirror"
				})
			.click(function(){
				if ( $( this ).find("input").attr("checked") ){
					demo.$demo.hide();
					demo.$code.show();
					}
				}),
		$demo_btn: $('#tab_demo')
			.button({
				type: "radio",
				name: "tabcodemirror",
				checked: true
				})
			.click(function(){
				if ( $( this ).find("input").attr("checked") ){
					demo.$demo.show();
					demo.$code.hide();
					if ( demo.codeMirrorReady )
						demo.execute(); 
					}
				}),
		// the button that opens the demo in a new window
		open: function(){
			window.open( demo.dir +'/'+ demo.file +'.htm' );								
			},
		// extract the body code from standalone demos
		extract: function( text ){
			// extract body
			text = text.split("<body>")[1].split("</body>")[0];
			// remove index link
			text = text.replace(/<a href=\".\/\">.+<\/a>/, "" );
			// fix all css urls
			text = text.replace(/url\("/g,'url("../source/'+ demo.dir +'/demo/');
			// fix all hrefs
			text = text.replace(/href="/g,'href="../source/'+ demo.dir +'/demo/');									
			// trim whitespace, remove tabs
			return $.trim( text );//.replace(/\t/g, demo.TAB );
			},
		// execute code from the edit box	
		execute: function(){
			// get the code to execute
			var code = demo.editor.getCode();
			// inject and execute new code...
			if ( code != demo.code )
				demo.empty().$demo.html( code ); 
			// remember the assigned code	
			demo.code = code;
			},
		// empty the demo
		empty: function(){
			// forget any errors...
			demo.error = false;
			// clean-up / remove old code...
			demo.$demo.find(":ux").ux(".destroy").end().empty();
			return demo;
			},
		// load a plugin demo from source URL
		load: function( src ){ 
			// stop if already loading...
			if ( !demo.codeMirrorReady || demo.loading || !src || demo.last == src ) return;			
			// parse the url hash >> "#directory/filename"
			var parts = ( String( src ).split("#")[1] || "" ).split("/"),
			// determine the directory and filename of the 
			directory =  parts[0], filename = parts[1] || "default";
			// validate what was parsed...
			if ( !directory || ( demo.dir == directory && demo.file == filename ) ) 
				return;
			demo.last = src; // remember the last source...
			// a new active plugin directory
			if ( directory != demo.dir ){
				// remeber the directory that is showing
				demo.dir = directory;
				// flag for AJAX loading...
				demo.loading += 1;
				// empty the old submenu
				demo.$subpop.html("");
				demo.$sub.hide();
				// load the new submenu
				$.ajax({
					url:  '../source/'+ demo.dir +'/demo/index.htm', 
					type: "POST",
					dataType: "text",
					success: function( data ){
						$('<div/>').html( demo.extract( data ) )
							.find('li').appendTo( demo.$subpop )
							.find('a').each(function(){
								var name = this.href.split("/").pop().split(".")[0];
								this.href = '#'+ demo.dir +'/'+ name;
								if ( name == filename ){
									demo.$active2 = $( this ).addClass("menu-active");
									demo.$sub.ux("button.content", '<span>&nbsp;&#x25BC;</span>'+ demo.$active2.text() );
									}
								});
						demo.$sub.show();	
						},
					complete: function(){
						demo.loading -= 1;
						}
					});	
				// highlight the correct menu item...
				demo.$active1.removeClass("menu-active");
				demo.$active1 = demo.$mainpop.find('a[href$=#'+ demo.dir +']').addClass("menu-active");
				demo.$main.ux("popdown.hide")
					.ux("button.content", '<span>&nbsp;&#x25BC;</span>'+ demo.$active1.text() );
				}
			// remember the filename that is showing
			demo.file = filename;
			// flag for AJAX loading...
			demo.loading += 1;
			// empty the previous demo...
			demo.empty();
			// load the new demo
			$.ajax({
				url: '../source/'+ demo.dir +'/demo/'+ demo.file + '.htm', 
				type: "POST",
				dataType: "text",
				success: function( data ){
					// manually empty the code mirror
					$('#editor_div iframe').contents().find("body").html("")
					// reset the code mirror history
					demo.editor.clearHistory();
					// throw new code against the mirror
					demo.editor.setCode( demo.extract( data ) );
					},
				error: function( xhr ){
					demo.editor.setCode(
						'<h2>'+ xhr.status+' / '+ xhr.statusText +'</h2>\n'
						+'<p><strong>demo/'+ demo.dir +'/'+ demo.file + '.htm</strong> could not be loaded.</p>'
						);	
					demo.error = true;
					},
				complete: function(){
					demo.loading -= 1;
					demo.execute();
					}
				});
			// highlight the correct menu item...
			demo.$active2.removeClass("menu-active");
			demo.$active2 = demo.$subpop.find('a[href$=#'+ demo.dir +'/'+ demo.file +']').addClass("menu-active");
			demo.$sub.ux("popdown.hide")
				.ux("button.content", '<span>&nbsp;&#x25BC;</span>'+ demo.$active2.text() );
			},
		// track ajax requests	
		loading: 0
		};
	// set the correct tab	
	demo.$demo_btn.click();
	// periodically inspect the url (capture clicks + forward/back)
	setTimeout(function(){
		// try to load the current hash
		demo.load( String( window.location ) );				
		// recurse...
		setTimeout( arguments.callee, 200 );
		}, 0 );
	});